home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / labeldisk / labeldisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-08  |  13.4 KB  |  493 lines

  1. /* 
  2.  * labeldisk.c --
  3.  *
  4.  *    Read and possibly change the disk label.
  5.  *
  6.  * Copyright (C) 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/cmds/labeldisk/RCS/labeldisk.c,v 1.15 92/02/06 12:05:21 voelker Exp Locker: voelker $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include "option.h"
  16. #include "disk.h"
  17. #include <sys/file.h>
  18. #include <stdio.h>
  19. #include <errno.h>
  20. #include <kernel/dev.h>
  21.  
  22. #define Min(a,b) (((a) < (b)) ? (a) : (b))
  23. /*
  24.  * Constants settable via the command line.
  25.  */
  26. char *fromName;         /* e.g. set to "/dev/rsd0" */
  27. char *toName;        /* e.g. set to "/dev/rsd0g" */
  28. Boolean writeLabel = FALSE;
  29. Boolean writeSun = FALSE;
  30. Boolean writeDec = FALSE;
  31. Boolean newLabel = FALSE;
  32. Boolean writeQuick = FALSE;
  33.  
  34. Option optionArray[] = {
  35.     {OPT_DOC,"",(Address)NIL,
  36.     "labeldisk [-from fromDevice] [-w] [-q] [-sun] [-dec] [-new] toDevice"},
  37.     {OPT_STRING, "from", (char *)&fromName,
  38.     "Read the disk label from this partition"},
  39.     {OPT_TRUE, "w", (Address)&writeLabel,
  40.     "Write a new disk label"},
  41.     {OPT_TRUE, "sun", (Address)&writeSun,
  42.     "Write a Sun label"},
  43.     {OPT_TRUE, "dec", (Address)&writeDec,
  44.     "Write a Dec label"},
  45.     {OPT_TRUE, "new", (Address)&newLabel,
  46.     "Ignore any old label"},
  47.     {OPT_TRUE, "q", (Address)&writeQuick,
  48.     "Copy label quickly, without prompting to change the label"}
  49. };
  50. int numOptions = sizeof(optionArray) / sizeof(Option);
  51.  
  52. static ReturnStatus    LabelDisk();
  53. static void        EditLabel();
  54. static void        InputNumber();
  55. static int        IsYes();
  56.  
  57. /*
  58.  *----------------------------------------------------------------------
  59.  *
  60.  * main --
  61.  *
  62.  *    Open the disk device and call LabelDisk.
  63.  *
  64.  * Results:
  65.  *    None.
  66.  *
  67.  * Side effects:
  68.  *    None.
  69.  *
  70.  *----------------------------------------------------------------------
  71.  */
  72. main(argc, argv)
  73.     int argc;
  74.     char *argv[];
  75. {
  76.     int openFlags;
  77.     int toStreamID;
  78.     int fromStreamID;
  79.     int tmp;
  80.  
  81.     argc = Opt_Parse(argc, argv, optionArray, numOptions);
  82.     if (argc != 2) {
  83.     if (argc == 1 && fromName != NULL && strlen(fromName) > 0) {
  84.         toName = fromName;
  85.     } else {
  86.         Opt_PrintUsage(argv[0], optionArray, numOptions);
  87.         exit(FAILURE);
  88.     }
  89.     } else {
  90.     if (fromName == NULL || strlen(fromName) == 0) {
  91.         fromName = argv[1];
  92.     }
  93.     toName = argv[1];
  94.     } 
  95.     if (writeSun || writeDec || writeQuick) {
  96.     writeLabel = TRUE;
  97.     }
  98.     if (writeLabel) {
  99.     openFlags = O_RDWR;
  100.     } else {
  101.     openFlags = O_RDONLY;
  102.     }
  103.     if ((writeSun?1:0)+(writeDec?1:0) > 1) {
  104.     fprintf(stderr,
  105.         "Can't specify more than one of -sun, -dec.\n");
  106.     Opt_PrintUsage(argv[0], optionArray, numOptions);
  107.     exit(FAILURE);
  108.     } 
  109.     fromStreamID = open(fromName, openFlags, 0);
  110.     if (fromStreamID < 0) {
  111.     perror("Can't open device");
  112.     exit(FAILURE);
  113.     }
  114.     tmp = strcmp(fromName, toName);
  115.     if (tmp) {
  116.     toStreamID = open(toName, openFlags, 0);
  117.     if (toStreamID < 0) {
  118.         perror("Can't open device");
  119.         exit(FAILURE);
  120.     }
  121.     } else {
  122.     toStreamID = fromStreamID;
  123.     }
  124.     if (LabelDisk(fromStreamID, toStreamID) != SUCCESS) {
  125.     if (errno == 0) {
  126.         fprintf(stderr, "labeldisk: Short read, or EOF encountered ");
  127.         fprintf(stderr, "on most likely an empty partition.\n");
  128.     } else {
  129.         perror("labeldisk");
  130.     }
  131.     }
  132.     exit(errno);
  133. }
  134.  
  135. /*
  136.  *----------------------------------------------------------------------
  137.  *
  138.  * LabelDisk --
  139.  *    Read and perhaps write the disk label.
  140.  *
  141.  * Results:
  142.  *    A status.
  143.  *
  144.  * Side effects:
  145.  *    Rewrites the partition information on the 0'th sector of the disk.
  146.  *
  147.  *----------------------------------------------------------------------
  148.  */
  149. static ReturnStatus
  150. LabelDisk(fromStreamID, toStreamID)
  151.     int fromStreamID;            /* Handle on raw input disk */
  152.     int toStreamID;                     /* Handle on raw output disk */
  153. {
  154.     Disk_Label             *diskLabelPtr;
  155.     int             n;
  156.     char             answer[80];
  157.     Disk_NativeLabelType    inLabel, outLabel;
  158.     static char                 buffer[1024], buffer2[1024];
  159.     ReturnStatus        status;
  160.     Ofs_DomainHeader            *headerPtr;
  161.  
  162.     if (writeSun) {
  163.     outLabel = DISK_SUN_LABEL;
  164.     } else if (writeDec) {
  165.     outLabel = DISK_DEC_LABEL;
  166.     } else {
  167.     outLabel = DISK_NO_LABEL;
  168.     }
  169.     diskLabelPtr = Disk_ReadLabel(fromStreamID);
  170.     if (newLabel || diskLabelPtr == NULL) {
  171.     if (!newLabel) {
  172.         printf("The disk does not have a label.\n");
  173.     }
  174.     if (!writeLabel) {
  175.         return FAILURE;
  176.     }
  177.     if (outLabel == DISK_NO_LABEL) {
  178.         printf("You must specify the -sun, or -dec option.\n");
  179.         return FAILURE;
  180.     }
  181.     inLabel = DISK_NO_LABEL;
  182.     diskLabelPtr = Disk_NewLabel(outLabel);
  183.     }
  184.     if (diskLabelPtr != NULL) {
  185.     inLabel = diskLabelPtr->labelType;
  186.     }
  187.     if (outLabel == DISK_NO_LABEL) {
  188.     outLabel = inLabel;
  189.     }
  190.     Disk_PrintLabel(diskLabelPtr);
  191.     if (!writeLabel) {
  192.     return SUCCESS;
  193.     }
  194.     if (inLabel != outLabel) {
  195.     /*
  196.      * At this point, the output label should be an empty buffer.
  197.      * diskHeaderPointer should be a valid label or empty buffer.
  198.      * diskInfoPtr should be have the proper sector values and string.
  199.      */
  200.     printf(
  201.       "Do you really want to replace a %s label with a %s label? (y/n) ",
  202.       Disk_GetLabelTypeName(inLabel), Disk_GetLabelTypeName(outLabel));
  203.     n = scanf("%s", answer);
  204.     if (n == EOF) {
  205.         exit(1);
  206.     }
  207.     if (strcasecmp(answer, "y")) {
  208.         exit(1);
  209.     }
  210.     }
  211.     if (!writeQuick) {
  212.     EditLabel(toStreamID, diskLabelPtr);
  213.     } else {
  214.     printf("\nCommit label? (y/n) ");
  215.     if (!IsYes()) {
  216.         exit(0);
  217.     }
  218.     }
  219.     if (inLabel != outLabel && fromStreamID == toStreamID) {
  220.     status = Disk_EraseLabel(fromStreamID, inLabel);
  221.     if (status != SUCCESS) {
  222.         printf("Unable to erase old label.\n");
  223.     }
  224.     }
  225.     printf("Write this label to all valid partitions? (y/n) ");
  226.     n = scanf("%s", answer);
  227.     if ((n == EOF) || strcasecmp(answer, "y")) {
  228.     printf("Writing disk label to %s.\n", toName);
  229.     status = Disk_WriteLabel(toStreamID, diskLabelPtr, outLabel);
  230.     return status;
  231.     } else {
  232.     int part, cyls, streamID, len, cantWriteToRawDisk = FALSE;
  233.     char c, *devName;
  234.  
  235.     len = strlen(toName);
  236.     devName = (char *)malloc(sizeof(char) * len + 1);
  237.         if (devName == NULL) {
  238.         perror("allocating string");
  239.         exit(FAILURE);
  240.     }
  241.     c = toName[len - 1];
  242.     if (c >= 'a' && c < 'i') {
  243.         /*
  244.          * the original destination name is a partition, 
  245.          * e.g. "/dev/rsd00a", so make sure to write the label
  246.          * to the beginning of the raw disk and then
  247.          * write the label to all valid partitions
  248.          */
  249.         sprintf(devName, "%s",toName);
  250.         devName[--len] = '\0';  
  251.         streamID = open(devName, O_RDWR, 0);
  252.     } else {
  253.         /*
  254.          * the original destination name is a raw disk,
  255.          * e.g. "/dev/rsd00", so write the label to the raw
  256.          * disk and then to all valid partitions
  257.          */
  258.         sprintf(devName, "%s",toName);
  259.         streamID = toStreamID;
  260.     }
  261.     printf("raw device: %s\n", devName);
  262.     if (streamID >= 0) {
  263.         status = Disk_WriteLabel(streamID, diskLabelPtr, outLabel);
  264.         if (status != SUCCESS) {
  265.         printf("Unable to write disk label to ");
  266.         printf("%s...skipping\n", devName);
  267.         cantWriteToRawDisk = TRUE;
  268.         }
  269.     } else {
  270.         cantWriteToRawDisk = TRUE;
  271.     }
  272.     devName[len + 1] = '\0';
  273.     for (part = 0 ; part < diskLabelPtr -> numPartitions; part++) {
  274.         cyls = diskLabelPtr->partitions[part].numCylinders;
  275.         if (cyls <= 0) {
  276.         continue;
  277.         }
  278.         devName[len] = 'a' + part;
  279.         printf("partition: %s\n", devName);
  280.         if (!strcmp(devName, fromName)) {
  281.         streamID = fromStreamID;
  282.         } else if (!strcmp(devName, toName)) {
  283.         streamID = toStreamID;
  284.         } else {
  285.         streamID = open(devName, O_RDWR, 0);
  286.         if (streamID < 0) {
  287.             perror("Can't open device");
  288.             exit(FAILURE);
  289.         }
  290.         }
  291.         status = Disk_HasFilesystem(streamID, diskLabelPtr);
  292.         if (status == DISK_HAS_NO_FS) {
  293.         printf("Could not find file system on ");
  294.         printf("%s...skipping\n", devName);
  295.         continue;
  296.         }
  297.         status = Disk_WriteLabel(streamID, diskLabelPtr, outLabel);
  298.         if (status) {
  299.         printf("Unable to write disk label to ");
  300.         printf("%s...skipping\n", devName);
  301.         } else {
  302.         /*
  303.          * Having written to the partition, if the partition
  304.          * starts at cylinder 0 then we have effectively
  305.          * written to the raw disk
  306.          */
  307.         if (diskLabelPtr->partitions[part].firstCylinder == 0) {
  308.             cantWriteToRawDisk = FALSE;
  309.         }
  310.         }
  311.     }
  312.     if (cantWriteToRawDisk == TRUE) {
  313.         devName[len] = '\0';
  314.         printf("Warning:  either couldn't open and write to");
  315.         printf("%s or\ncouldn't write to a valid partition ", devName);
  316.         printf("that starts at cylinder 0.\n");
  317.     }
  318.     }
  319.     return status;
  320. }
  321.  
  322. /*
  323.  *----------------------------------------------------------------------
  324.  *
  325.  * EditLabel --
  326.  *
  327.  *    Interactively edits the disk label.
  328.  *
  329.  * Results:
  330.  *    None.
  331.  *
  332.  * Side effects:
  333.  *    Changes contents of the disk label.
  334.  *
  335.  *----------------------------------------------------------------------
  336.  */
  337. static void
  338. EditLabel(streamID, labelPtr)
  339.     int            streamID;    /* Handle on raw disk */
  340.     Disk_Label        *labelPtr;    /* The disk label */
  341. {
  342.     int                 numHeads, numSectors, part;
  343.     ReturnStatus        status = SUCCESS;
  344.     int                 first, cyls, last, lastSector, lastCyl;
  345.     char            buffer[DEV_BYTES_PER_SECTOR];
  346.     char        *tmpPtr;
  347.     int            labelLen;
  348.  
  349. editLabel:
  350.     printf("Size of ascii label (%d): ", labelPtr->asciiLabelLen);
  351.     InputNumber(&labelPtr->asciiLabelLen);
  352.     printf("ascii label (%s): ", labelPtr->asciiLabel);
  353.     tmpPtr = fgets(buffer, labelPtr->asciiLabelLen,stdin);
  354.     if (tmpPtr == NULL) {
  355.     exit(1);
  356.     }
  357.     printf("%d\n", strlen(buffer));
  358.     if (strlen(buffer) > 1) {
  359.     labelLen = Min(strlen(buffer), labelPtr->asciiLabelLen);
  360.     strncpy(labelPtr->asciiLabel, buffer, labelLen);
  361.     labelPtr->asciiLabel[labelLen - 1] = '\0';
  362.     }
  363.     printf("Number of heads (%d): ", labelPtr->numHeads);
  364.     InputNumber(&labelPtr->numHeads);
  365.     printf("Number of sectors per track (%d): ", labelPtr->numSectors);
  366.     InputNumber(&labelPtr->numSectors);
  367.     printf("Number of cylinders (%d): ", labelPtr->numCylinders);
  368.     InputNumber(&labelPtr->numCylinders);
  369.     printf("Number of alternate cylinders (%d): ", labelPtr->numAltCylinders);
  370.     InputNumber(&labelPtr->numAltCylinders);
  371.     printf("Starting sector of boot program (%d): ", labelPtr->bootSector);
  372.     InputNumber(&labelPtr->bootSector);
  373.     printf("Number of boot sectors (%d): ", labelPtr->numBootSectors);
  374.     InputNumber(&labelPtr->numBootSectors);
  375.     printf("Starting sector of summary info (%d): ", labelPtr->summarySector);
  376.     InputNumber(&labelPtr->summarySector);
  377.     printf("Starting sector of domain header (%d): ", labelPtr->domainSector);
  378.     InputNumber(&labelPtr->domainSector);
  379.     numHeads = labelPtr->numHeads;
  380.     numSectors = labelPtr->numSectors;
  381.     if (numHeads * numSectors != 
  382.     labelPtr->numHeads * labelPtr->numSectors) {
  383.     printf(
  384.     "The size of a cylinder changed so I have to zero the partition map.\n");
  385.     for (part=0 ; part < labelPtr->numPartitions; part++) {
  386.         labelPtr->partitions[part].firstCylinder = 0;
  387.         labelPtr->partitions[part].numCylinders = 0;
  388.     }
  389.     }
  390.     for (part=0 ; part < labelPtr->numPartitions; part++) {
  391.     first = labelPtr->partitions[part].firstCylinder;
  392.     cyls = labelPtr->partitions[part].numCylinders;
  393.     last = (cyls > 0) ? (cyls + first - 1) : first;
  394.     printf("\n%c: First %4d Last %4d Num %4d (%7d sectors)\n",
  395.         'a' + part, first, last, cyls,
  396.         cyls *  labelPtr->numHeads * labelPtr->numSectors);
  397.     printf("First (%d): ", labelPtr->partitions[part].firstCylinder);
  398.     InputNumber(&labelPtr->partitions[part].firstCylinder);
  399.     printf("Num (%d): ", labelPtr->partitions[part].numCylinders);
  400.     InputNumber(&labelPtr->partitions[part].numCylinders);
  401.     }
  402.     printf("\nNew Label\n");
  403.     Disk_PrintLabel(labelPtr);
  404.     /* Determine the last cylinder */
  405.     lastCyl = 0;
  406.     for (part=0 ; part < labelPtr->numPartitions; part++) {
  407.     first = labelPtr->partitions[part].firstCylinder;
  408.     cyls = labelPtr->partitions[part].numCylinders;
  409.     last = (cyls > 0) ? (cyls + first - 1) : first;
  410.     if (last>lastCyl) {
  411.         lastCyl = last;
  412.     }
  413.     }
  414.     lastSector = (lastCyl + 1) * numHeads * numSectors - 1;
  415.     status = Disk_SectorRead(streamID, lastSector, 1, buffer);
  416.     if (status != 0) {
  417.     printf("I couldn't read the last sector (sector %d)!!!\n", lastSector);
  418.     printf("Either the disk isn't as big as you think it is,\n");
  419.     printf("or the device is not a raw device.\n");
  420.     printf("(cylinders=%d, numHeads=%d, numSectors=%d)\n", lastCyl+1,
  421.         numHeads, numSectors);
  422.     printf("Status = %x\n", status);
  423.     }
  424.     printf("\nCommit new label? (y/n) ");
  425.     if (!IsYes()) {
  426.     printf("Try again\n");
  427.     goto editLabel;
  428.     }
  429. }
  430.  
  431. /*
  432.  *----------------------------------------------------------------------
  433.  *
  434.  * InputNumber --
  435.  *
  436.  *    Get a number interactively.
  437.  *
  438.  * Results:
  439.  *    None.
  440.  *
  441.  * Side effects:
  442.  *    Stuff is read from stdin..
  443.  *
  444.  *----------------------------------------------------------------------
  445.  */
  446. static void
  447. InputNumber(number)
  448.     int        *number;    /* Place to store number. */
  449. {
  450.     int n, val;
  451.     char buffer[80];
  452.  
  453.     if (fgets(buffer, 80, stdin) == NULL) {
  454.     exit(1);
  455.     }
  456.     n = sscanf(buffer, "%d", &val);
  457.     if (n < 1) {
  458.     return;
  459.     }
  460.     *number = val;
  461. }
  462.  
  463. /*
  464.  *----------------------------------------------------------------------
  465.  *
  466.  * IsYes --
  467.  *
  468.  *    Returns TRUE if user answers y.
  469.  *
  470.  * Results:
  471.  *    TRUE or FALSE.
  472.  *
  473.  * Side effects:
  474.  *    None.
  475.  *
  476.  *----------------------------------------------------------------------
  477.  */
  478. static int
  479. IsYes()
  480. {
  481.     int n;
  482.     char answer[80];
  483.     n = scanf("%s", answer);
  484.     if (n == EOF) {
  485.     exit(1);
  486.     }
  487.     if (strcmp(answer, "y")==0) {
  488.     return TRUE;
  489.     } else {
  490.     return FALSE;
  491.     }
  492. }
  493.